# file_service.py
import io
import os

from werkzeug.datastructures import FileStorage

from common.exception.exception import BusiException
from common.exception.exception_enum import BusiExceptionEnum
from common.log.logging import log
from common.oss.oss import OssObject
from common.oss.oss_builder import OssApiBuilder
from common.utils.config_reader import get_config


class FileService:

    def __init__(self):
        self.oss_client = None
        self.init_oss_client()
        # 允许的文件类型
        allow_file_types_config = get_config("server.upload.allow-file-types", "*")
        # 从配置文件中获取允许的文件类型
        self.allowed_file_types = allow_file_types_config.split(',')
        log.info(f"allow upload file types: {self.allowed_file_types}")

    def init_oss_client(self):
        """
        根据配置进行oss客户端初始化
        :return: OssApi
        """
        self.oss_client = OssApiBuilder().build_client()

    def upload(self, file: FileStorage) -> OssObject:
        """
        保存上传的文件到指定路径。

        参数:
        - file: FileStorage 对象，表示上传的文件。

        返回:
        - 保存的文件路径。
        """
        if file.filename == '':
            raise BusiException(BusiExceptionEnum.NO_FILE_PART)

        if not file:
            raise BusiException(BusiExceptionEnum.FILE_UPLOAD_ERROR)

        if not file or file.filename == '':
            raise BusiException(BusiExceptionEnum.NO_SELECTED_FILE)

        filename = file.filename
        # 文件扩展名
        file_extension = os.path.splitext(filename)[1].lower()[1:]
        # 校验上传文件类型
        self.check_upload_file_type(file_extension)

        try:
            # 确保上传目录存在
            oss_object = self.oss_client.upload(filename, io.BytesIO(file.read()))
            log.info(f'File {filename} successfully uploaded')
            return oss_object
        except Exception as e:
            log.error(f'Error uploading file: {e}')
            raise

    def check_upload_file_type(self, file_extension):
        """
        检查上传文件类型是否符合约束
        :param file_extension: 文件后缀名
        """
        if "*" not in self.allowed_file_types and file_extension not in self.allowed_file_types:
            raise BusiException(BusiExceptionEnum.INVALID_FILE_TYPE)

    def get_object(self, object_id: str) -> io.IOBase:
        # 获取文件逻辑
        file_stream = self.oss_client.get_object(object_id)
        return file_stream
